﻿namespace Config
{
	using System;
	using UnityEngine;
	using System.IO;
	using System.Collections;
	using System.Collections.Generic;
	using System.Security;
	using Mono.Xml;
	using System.Linq;
	using CxExtension;
	using LitJson;
	using Table = System.Collections.Generic.Dictionary<string, string>;
	public class ConfigManager
	{
		//private static Dictionary<Type,Dictionary<string,BaseConfig>> tables = new Dictionary<Type,Dictionary<string,BaseConfig>>();
		public string path = "Config/Json";
		private const string classKey = "classKey";
		private List<string> files;
		private Func<string, List<Table>> mParseFunc;

		public ConfigManager Instance
		{
			get { return SingletonObject<ConfigManager>.GetInstance(); }
		}

		public ConfigManager()
		{
			mParseFunc = ParseCTV2Map;
		}

		// Use this for initialization
		/// <summary>
		/// 读取path路径下面的所有文件
		/// </summary>
		public void Load()
		{
			TextAsset[] texts = Resources.LoadAll<TextAsset>(path);
			files = new List<string>(texts.Length);
			foreach (var item in texts)
			{
				files.Add(item.text);
				Resources.UnloadAsset(item);
			}
			foreach (var item in files)
			{
				ParseToInstances(item);
			}
		}
		/// <summary>
		/// 读取path路径指向的xml配置表并解析成T类型列表
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="path"></param>
		/// <returns></returns>
		public List<T> Load<T>(string path) where T : BaseConfig
		{
			var textAsset = Resources.Load<TextAsset>(path);
			if (!textAsset)
			{
				Debug.LogErrorFormat("没有读取到文件:{0}", path);
				return null;
			}
			var text = textAsset.text;
			var list = ParseToInstances<T>(text);
			Resources.UnloadAsset(textAsset);
			return list;
		}
		public void ParseToInstances(string text)
		{
			List<Table> v = ParseData2Maps(text);
			foreach (var i1 in v)
			{
				ParseToInstance(i1);
			}
		}
		/// <summary>
		/// 把字符串解析成map key代表每一条配置的id;value代表条配置的所有属性和值
		/// </summary>
		/// <param name="text"></param>
		/// <param name="fileType"></param>
		/// <returns></returns>
		private List<Table> ParseData2Maps(string text, int fileType = 1)
		{
			List<Table> v = null;
			v = mParseFunc(text);

			return v;
		}

		public void SetParse(Func<string, List<Table>> func)
		{
			mParseFunc = func;
		}
		public List<T> ParseToInstances<T>(string text) where T : BaseConfig
		{
			var v = ParseData2Maps(text);
			var list = v.ConvertAll<T>(ParseToInstance<T>);
			return list;
		}
		public T ParseToInstance<T>(Table map) where T : BaseConfig
		{
			var classname = map[classKey];
			var obj = typeof(BaseConfig).GetSubInstanceByName(classname);
			if (obj != null)
			{
				var cof = obj as T;
				cof.Parse2Map(map);
				return cof;
			}
			return null;
		}
		public BaseConfig ParseToInstance(Table map)
		{
			var classname = map[classKey];
			var obj = typeof(BaseConfig).GetSubInstanceByName(classname);
			if (obj != null)
			{
				var cof = obj as BaseConfig;
				cof.Parse2Map(map);
				return cof;
			}
			return null;
		}

		public List<Table> ParseCTV2Map(string item)
		{
			var spline = "\r\n";
			var splie = '\t';
			var rows = item.Split(spline);
			if (rows.Length == 0)
			{
				Debug.LogErrorFormat("解析失败 错误的CTV格式");
			}
			var insMap = new List<Table>();
			var rowsQue = new Queue<string>(rows);
			var classNameStr = rowsQue.Dequeue();
			if (string.IsNullOrEmpty(classNameStr))
			{
				Debug.LogErrorFormat("空的className");
				return insMap;
			}
			var className = classNameStr.Split(splie)[0];
			rowsQue.Dequeue();
			rowsQue.Dequeue();
			var propertys = rowsQue.Dequeue().Split(splie);
			foreach (var it in rowsQue)
			{
				var lie = it.Split('\t');
				var table = new Table();
				table[classKey] = className;
				for (var i = 0; i < lie.Length; i++)
				{
					var key = propertys[i];
					var value = lie[i];
					table[key] = value;
				}
				insMap.Add(table);
			}
			return insMap;
		}
		public List<Table> ParseXml2Map(string item)
		{
			var insMap = new List<Table>();
			var securityParser = new SecurityParser();
			securityParser.LoadXml(item);
			var xml = securityParser.ToXml();
			foreach (var it in xml.Children)
			{
				var node = it as SecurityElement;
				var map = ParseXml2Map(node);
				insMap.Add(map);
			}
			return insMap;
		}
		public Table ParseJson2Map(JsonData item)
		{
			var map = new Table();
			foreach (var it in item)
			{
				map[it.ToString()] = (string)item[it.ToString()];
			}
			return map;
		}
		public List<Table> ParseJson2Maps(string item)
		{
			var maps = new List<Table>();
			var json = JsonMapper.ToObject(item);

			string class_name = json["class_name"].ToString();

			var datas = json["dataMaps"];
			if (datas.IsArray)
			{
				foreach (var it in datas)
				{
					var map = ParseJson2Map((JsonData)it);
					map[classKey] = class_name;
					maps.Add(map);
				}
			}
			return maps;
		}

		public Table ParseXml2Map(SecurityElement elem)
		{
			var map = new Table();
			map[classKey] = elem.Tag;
			/*foreach(var item in elem.Children)
			{
				var se = item as SecurityElement;
				var key = se.Tag;
				var value = se.Attributes["value"].ToString();
				map[key] = value;
			}*/
			foreach (DictionaryEntry item in elem.Attributes)
			{
				map[item.Key.ToString()] = item.Value.ToString();
				//map.Add()
			}
			return map;
		}
	}
}
